// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Permissive License.
// See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx.
// All other rights reserved.
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls;
using System.Drawing;
using System.Web.UI;
using System.ComponentModel;
using System.Globalization;
using System.Web;

namespace RealWorld.Grids
{
    public class FrozenGridView : GridView
    {
        private const string FrozenTopCssClass = "frozenTop";

        #region Properties

        [Browsable(true), DefaultValue(true), Category("Behavior"), DisplayName("Freeze Header")]
        public bool FreezeHeader
        {
            get
            {
                object val = this.ViewState["FreezeHeader"];
                if (null == val)
                {
                    return true;
                }

                return (bool)val;
            }
            set
            {
                this.ViewState["FreezeHeader"] = value;
            }
        }

        [Browsable(true), DefaultValue(ScrollBars.None), Category("Behavior")]
        public ScrollBars Scrolling
        {
            get
            {
                object val = this.ViewState["Scrolling"];
                if (null == val)
                {
                    return ScrollBars.None;
                }

                return (ScrollBars)val;
            }
            set
            {
                this.ViewState["Scrolling"] = value;
            }
        }

        public Unit ScrollWidth
        {
            get
            {
                return base.Width;
            }
            set
            {
                base.Width = value;
            }
        }

        public override Unit Width
        {
            get
            {
                object val = this.ViewState["DivWidth"];
                if (null == val)
                {
                    return Unit.Empty;
                }

                return (Unit)val;
            }
            set
            {
                this.ViewState["DivWidth"] = value;
            }
        }

        public Unit ScrollHeight
        {
            get
            {
                return base.Height;
            }
            set
            {
                base.Height = value;
            }
        }

        public override Unit Height
        {
            get
            {
                object val = this.ViewState["DivHeight"];
                if (null == val)
                {
                    return Unit.Empty;
                }

                return (Unit)val;
            }
            set
            {
                this.ViewState["DivHeight"] = value;
            }
        }

        private string OverflowX
        {
            get
            {
                if (this.Scrolling == ScrollBars.Horizontal || this.Scrolling == ScrollBars.Both)
                {
                    return "scroll";
                }
                else if (this.Scrolling == ScrollBars.Auto)
                {
                    return "auto";
                }
                else
                {
                    return "visible";
                }
            }
        }

        private string OverflowY
        {
            get
            {
                if (this.Scrolling == ScrollBars.Vertical || this.Scrolling == ScrollBars.Both)
                {
                    return "scroll";
                }
                else if (this.Scrolling == ScrollBars.Auto)
                {
                    return "auto";
                }
                else
                {
                    return "visible";
                }
            }
        }

        #endregion

        #region Overrides
        protected override void OnDataBound(EventArgs e)
        {
            base.OnDataBound(e);

            this.FreezeCells();
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            if (this.FreezeHeader && !this.Page.Items.Contains(FrozenGridView.FrozenTopCssClass))
            {
                this.Page.Items[FrozenGridView.FrozenTopCssClass] = "1";
                FrozenTopStyle frozenTopStyle = new FrozenTopStyle();
                this.Page.Header.StyleSheet.CreateStyleRule(frozenTopStyle, null, "." + FrozenGridView.FrozenTopCssClass);
            }
        }

        protected override void Render(HtmlTextWriter writer)
        {
            if (this.Page != null)
            {
                this.Page.VerifyRenderingInServerForm(this);
            }
            this.PrepareControlHierarchy();
            if (!this.DesignMode)
            {
                string clientID = this.ClientID;
                if (clientID == null)
                {
                    throw new HttpException("FrozenGridView Must Be Parented");
                }

                writer.AddAttribute(HtmlTextWriterAttribute.Id, String.Format(CultureInfo.InvariantCulture, "__gv{0}__div", clientID), true);
                writer.AddStyleAttribute(HtmlTextWriterStyle.OverflowX, this.OverflowX);
                writer.AddStyleAttribute(HtmlTextWriterStyle.OverflowY, this.OverflowY);
                if (!this.Width.IsEmpty)
                {
                    writer.AddStyleAttribute(HtmlTextWriterStyle.Width, this.Width.ToString(CultureInfo.InvariantCulture));
                }
                if (!this.Height.IsEmpty)
                {
                    writer.AddStyleAttribute(HtmlTextWriterStyle.Height, this.Height.ToString(CultureInfo.InvariantCulture));
                }
                writer.AddStyleAttribute(HtmlTextWriterStyle.Position, "relative");
                writer.AddStyleAttribute(HtmlTextWriterStyle.BorderColor, "Black");
                writer.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth, "3");
                writer.AddStyleAttribute(HtmlTextWriterStyle.BorderStyle, "solid");
                writer.RenderBeginTag(HtmlTextWriterTag.Div);
            }
            this.RenderContents(writer);
            if (!this.DesignMode)
            {
                writer.RenderEndTag();
            }
        }

        #endregion

        private void FreezeCells()
        {
            if (this.FreezeHeader)
            {
                foreach (DataControlFieldHeaderCell th in this.HeaderRow.Cells)
                {
                    th.CssClass = FrozenGridView.FrozenTopCssClass + " " + th.CssClass;
                }
            }
        }

        private class FrozenTopStyle : Style
        {
            internal FrozenTopStyle()
            {
            }

            protected override void FillStyleAttributes(CssStyleCollection attributes, IUrlResolutionService urlResolver)
            {
                base.FillStyleAttributes(attributes, urlResolver);

                attributes[HtmlTextWriterStyle.Top] = "expression(this.offsetParent.scrollTop)";
                attributes[HtmlTextWriterStyle.Position] = "relative";
                attributes[HtmlTextWriterStyle.ZIndex] = "2";
            }
        }
    }
}
